[comment {-*- tcl -*- doctools manpage}]
[manpage_begin midi n 0.11]
[copyright {2006-2008 Jos Decoster <jos.decoster@gmail.com>}]
[moddesc {Midi file, track and event handling}]
[titledesc {Package to handle midi files, tracks and events}]
[require Tcl 8.4]
[description]
[para]

This page describes the Tcl [package midi] package to process midi files. The
commands to read, write, create and edit midi files are discussed here.

[para]

The [package midi] package adds the namespace midi to the Tcl
interpreter in which it is loaded. In this namespace, the main commands to
work with midi files are created:

[list_begin definitions]
[lst_item midi::file]
[lst_item midi::track]
[lst_item midi::event]
[list_end]

[para] 

The file and track commands have an object interface, much like Tk
widgets. Midi events are represented as a list of integers.

[section midi::file]

[list_begin definitions]

[call [cmd midi::file] [opt [arg options]] ...]

This command will create a midi file object and returns a unique midi file
id. This id should be used to manipulate the midi file later on. Known options
are: 

[list_begin opt]

[opt_def -type integer]

Set the midi file type. Must be [const 0], [const 1] or [const 2]. Default value is 1.

[opt_def -time_division_type string]

Set the time divisiob type used in the midi file. Must be 
[const ticks_per_beat] or [const frames_per_second]. Default values is [const ticks_per_beat].

[opt_def -ticks_per_beat integer]

Sets the number of ticks per beat (quarter note), only used when the time 
division type is [const ticks_per_beat]. Default value is 480.

[opt_def -frames_per_second integer]

Set the number of frames per second, only used when the time division type is 
[const frames_per_second]. Default value is -1.

[opt_def -ticks_per_frame integer]

Set the number of ticks per frame, only used when the time division type is 
[const frames_per_second]. Default value is -1.

[opt_def -tracks listOfTrackIds]

Set the track to be included in the midi file. The tracks must be specified as
a list of tracks id's obtained by calling the [cmd midi::track] command. By default, no tracks are added.

[opt_def "" ""]

[list_end]

[call [arg midiFileId] [method destroy]]

Reset and destroy a midi file object.

[call [arg midiFileId] [method reset]]

Reset a midi file object. Resetting a midi file object will clear the type and
timing information and destroy all tracks (with reference count zero) of the
midi file.

[call [arg midiFileId] [method validate]]

Validates a midi file object, including the tracks. Only the options required
for a specific time division type are checked.

[call [arg midiFileId] [method validate_option] [arg option] [arg value]]

Validates a midi file object-option value. All options will be validated, even
if a specified option is not necessary according to the time division type. All
options accepted by the [cmd midi::file] command can be specified.

[call [arg midiFileId] [method cget] [arg option]]

Returns the current value of the configuration option given by [arg option]. 
[arg Option] may have any of the values accepted by the 
[cmd midi::file] command.

[call [arg midiFileId] [method configure]]

Returns a list describing all of the available options. The returned list
contains a sublist for each known option with the following elements: the
option, the default value and the current value. Information is returned for
all options accepted by the [cmd midi::file] command.

[call [arg midiFileId] [method configure] [arg option]]

Returns list describing the named option. [arg Option] may have any of the
values accepted by the [cmd midi::file] command. The returned list contains 3
elements: the option, the default value and the current value.

[call [arg midiFileId] [method configure] [arg "option value"] ...]

Modifies the given midi file option(s) to have the given value(s). The command
returns an empty string. [arg Option] may have any of the values accepted by
the [cmd midi::file] command.

[call [arg midiFileId] [method read] [arg fileName]]

Reads the specified midi file into the midi file object.

[call [arg midiFileId] [method write] [arg fileName] [opt [arg "option value ..."]]]

Writes the contents of the midi file object into the specified file. Known
options are:

[list_begin opt]

[opt_def -running_status boolean]

If set to true, the midi file will be written with running status, making the
resulting output file smaller. If set to false (default), the midi file will be
written without running status.

[opt_def -tracks listOfTrackIds]

Only write the specified tracks to the output file.

[opt_def "" ""]

[list_end]

[call [arg midiFileId] [method dump] [opt [arg "option value ..."]]]

Writes a textual representation of the midi file object contents into the file
specified with the -file option. If no file is specified, returns the textual
representation of the midi file as a string. Known options are:

[list_begin opt]

[opt_def -file path]

Dump the midi file to the specified output file.

[opt_def -tracks listOfTrackIds]

Only dump the specified tracks.

[opt_def "" ""]

[list_end]

[call [arg midiFileId] [method flatten] [opt [arg "option value ..."]]]

Creates a one track representation of a multi track midi file. This command
will return a list of two element lists. The first element in each sub-list
contains the delta time until the event associated with it can be
processed. The second element in each sub-list contains a list of events,
represented as lists of integers. Known options are:

[list_begin opt]

[opt_def -include_meta listOfMetaEventTypes]

Only include Meta events of specified types in the flattened
output. Check [cmd midi::event::type_meta_event] for known Meta event
types.

[opt_def -no_meta boolean]

Do not include Meta events in the flattened output.

[opt_def -no_sys_ex boolean]

Do not include SysEx events in the flattened output.

[opt_def -tracks listOfTrackIds]

Only flatten the specified tracks.

[opt_def "" ""]

[list_end]

[call [arg midiFileId] [method clicks] [arg "noteLength"]]

Calculates the length of a note in clicks for common note lengths. Lengths 
understood by this method are: [const 1], [const 1.], [const 1/2], 
[const 1/2.], [const 1/2t], [const 1/4], [const 1/4.], [const 1/4t], 
[const 1/8], [const 1/8.], [const 1/8t], [const 1/16], [const 1/16.], 
[const 1/16t], [const 1/32], [const 1/32.], [const 1/32t], [const 1/64], 
[const 1/64.] and [const 1/64t.]  Lengths with a [const .] (dot) add half of 
the length to the fraction, lengths with a [const t] are used for triplets. 
This functions can only be used when the [option -time_division_type] option is
set to [const ticks_per_beat] and the [option -ticks_per_beat] option has been 
initialised.

[call [arg midiFileId] [method measure] [opt [arg "option value ..."]]]

This command can be used to generate event list from a simplied input format. By
only specifying note names and durations, an event list suitable for midi-tracks
can be obtained. This command will only generate note-on and note-off event,
other event still need to be added to the event list with the [cmd midi::event]
command. Only a list of non-overlapping notes can be specified. It durations of
notes overlap, create different event-lists with multiple calls to this command
and later on merge the resulting event lists with the [cmd midi::merge] command.

[list_begin opt]

[opt_def -channel integer] Channel on which to play the specified notes.

[opt_def -events listOfListOfNotes] A list of note-lists. Each such note-list
contains a duration, a list of notes and optionally a velocity. A duration must
be specified as a note-length understood by the [cmd midi::file::clicks]
method. Notes can be specified using their midi note-number or their
note-name. Check the [sectref Notes] section for valid note numbers and valid
note names. In addition to the notes found in that section, it is possible to
use [const r] or [const R] to specify a rest. The optional velocity must be an
integer in the range 0..127. Default value is 127.

The following example show how to generate an event list of a C-major scale
played as quarter notes and followed by a C-major chord on channel 4:

[example_begin]
set mf [lb]midi::file -type 1 -time_division_type ticks_per_beat -ticks_per_beat 480[rb]
set el [lb]$mf measure -channel 4 -events {{1/4 C5} {1/4 D5} {1/4 E5} {1/4 F5} {1/4 G5} {1/4 A5} {1/4 B5} {1/4 C6} {1/1 {C5 E5 G5 C6}}}[rb]
[example_end]

Check the [sectref Examples] sections for more examples of using this method.

[opt_def "" ""]

[list_end]

[list_end]

[section midi::track]

[list_begin definitions]

[call [cmd midi::track] [opt [arg options]] ...]

This command will create a midi track object and return a unique midi track
id. This id should be used to manipulate the midi track later on. Known options
are:

[list_begin opt]

[opt_def -events listOfEvents]

Specifies a list of events with associated delta-time for the midi track. An
event with its associated delta-time is represented as a list of the delta-time
and a list of integers representing the event. By default, no events are added 
to a track. A delta time specifies the time to wait before processing the 
associated event. A delta time is expressed in clock ticks. When using 
[const ticks_per_beat] as time division type, the duration of a note can be 
calculated based on the specified ticks per beat. When 480 clock clicks are 
required for a quarter note, the length in clicks of other note lengths is as 
follows: 

[example_begin]
lengthInClicks = 480.0 * 4 * length
[example_end]

Using this function, the lengths of different notes can be calculated:

[example_begin]
length length in clicks
------ ----------------
1                  1920
1/2                 960
1/4                 480
1/8                 240
1/16                120
1/32                 60
1/64                 30
[example_end]

The [cmd midi::file::clicks] method can be used to calculate lengths in clicks 
for common note lengths.

[opt_def "" ""]

[list_end]

[call [arg midiTrackId] [method destroy]]

Reset and destroy a midi track object.

[call [arg midiTrackId] [method reset]]

Reset a midi track object. Resetting a midi track object removes all events
from the midi track.

[call [arg midiTrackId] [method validate]]

Validates a midi track object, including the events.

[call [arg midiTrackId] [method validate_option] [arg option] [arg value]]

Validates a midi track object option value. All options accepted by the 
[cmd midi::track] command can be specified.

[call [arg midiTrackId] [method cget] [arg option]]

Returns the current value of the configuration option given by [arg option]. 
[arg Option] may have any of the values accepted by the 
[cmd midi::track] command.

[call [arg midiTrackId] [method configure]]

Returns a list describing all of the available options. The returned list
contains a sublist for each known option with the following elements: the
option, the default value and the current value. Information is returned for
all options accepted by the [cmd midi::track] command.

[call [arg midiTrackId] [method configure] [arg option]]

Returns list describing the named option. [arg Option] may have any of the
values accepted by the [cmd midi::track] command. The returned list contains 3
elements: the option, the default value and the current value.

[call [arg midiTrackId] [method configure] [arg "option value"] ...]

Modifies the given midi track option(s) to have the given value(s). The command
returns an empty string. [arg Option] may have any of the values accepted by
the [cmd midi::track] command.

[call [arg midiTrackId] [method dump]]

Returns a textual representation of the midi track.

[list_end]

[section midi::event]

Events are represented as a list of integers. Each integer contains the value
of a byte in the binary midi event as stored in a midi file. The commands
listed below make it easier to create and manipulate midi events. These 
commands offer a configure interface. Supported events with associated options 
can be found in the [sectref Events] section.

[list_begin definitions]

[call [cmd midi::event] [arg type] [opt [arg options]] ...] 

Creates a new event of the specified type. Check the [sectref Events] section
for valid event types and associated options. The newly created event is
returned as a list of integers. This list must be specified with the other
event commands or when adding events to a track.
 
[call [cmd midi::event::reset] [arg intList]]
 
This command returns a list of integers for an event of the same type but with
all option values set to their defautl values.

[call [cmd midi::event::validate] [arg intList]] 

Checks if the specified list of integers is a valid event. 

[call [cmd midi::event::validate_option] [arg intList] [opt [arg options]] ...] 

Validates a midi event object option value. All options accepted by the 
midi event type can be specified.

[call [cmd midi::event::cget] [arg intList] [arg option]]

Returns the current value of the configuration option given by [arg option]. 
[arg Option] may have any of the values accepted by the event type.
 
[call [cmd midi::event::configure] [arg intList]]

Returns a list describing all of the available options for the type of the
specified event. The returned list contains a sublist for each known option
with the following elements: the option, the default value and the current
value.
 
[call [cmd midi::event::configure] [arg intList] [arg option]]

Returns list describing the named option. [arg Option] may have any of the
values accepted by the event type. The returned list contains 3 elements: the
option, the default value and the current value.
 
[call [cmd midi::event::configure] [arg intList] [arg "option value"] ...]
 
Modifies the given midi event option(s) to have the given value(s). The command
returns an empty string. [arg Option] may have any of the values accepted by
the event type.

[call [cmd midi::event::type] [arg intList]]
 
Return the type of the specified event. Possible return values are: 
[const note_off] [const note_on] [const note_aftertouch] [const controller]
[const program_change] [const channel_aftertouch] [const pitch_bend] 
[const Meta] [const SysEx]

[call [cmd midi::event::type_meta_event] [arg intList]]

Returns meta event type. Possible return values are: 
[const sequence_number] [const copyright] [const track_name] 
[const instrument_name] [const lyric] [const marker] [const cue_point]
[const program_name] [const device_name] [const channel] [const port] 
[const end_of_track] [const tempo] [const smpte_offset] [const time_signature] 
[const key_signature] [const sequencer_specific] [const meta_unknown]

[call [cmd midi::event::dump] [arg intList]]

Returns a textual representation of the midi event.

[list_end]

[section Examples]

The following example creates a midi file with 4 tracks. All events are
generated using the [cmd midi::event] command.

[example_begin]
package require midi

# Create midi file and initialise time division info
set mf [lb]midi::file -type 1 -time_division_type ticks_per_beat -ticks_per_beat 480[rb]

# Control track
set t1el {}
lappend t1el [lb]list 0 [lb]midi::event text -value "control track"[rb][rb]
lappend t1el [lb]list 0 [lb]midi::event tempo -tempo 0X7A120[rb][rb] ;# 120 Beats per minute
lappend t1el [lb]list 0 [lb]midi::event end_of_track[rb][rb]
set t1 [lb]midi::track -events $t1el[rb]

# Piano track
set t2el {}
lappend t2el [lb]list 0 [lb]midi::event text -value "Piano track"[rb][rb]
lappend t2el [lb]list 0 [lb]midi::event program_change -channel 0 -program "Electric Piano 2"[rb][rb]

lappend t2el [lb]list 0                [lb]midi::event note_on  -channel 0 -note C4 -velocity 127[rb][rb]
lappend t2el [lb]list [lb]$mf clicks 1/1[rb] [lb]midi::event note_off -channel 0 -note C4 -velocity 127[rb][rb]

lappend t2el [lb]list 0                [lb]midi::event note_on  -channel 0 -note E4 -velocity 127[rb][rb]
lappend t2el [lb]list [lb]$mf clicks 1/1[rb] [lb]midi::event note_off -channel 0 -note E4 -velocity 127[rb][rb]

lappend t2el [lb]list 0                [lb]midi::event note_on  -channel 0 -note G4 -velocity 127[rb][rb]
lappend t2el [lb]list [lb]$mf clicks 1/1[rb] [lb]midi::event note_off -channel 0 -note G4 -velocity 127[rb][rb]

lappend t2el [lb]list 0                [lb]midi::event note_on  -channel 0 -note C5 -velocity 127[rb][rb]
lappend t2el [lb]list [lb]$mf clicks 1/1[rb] [lb]midi::event note_off -channel 0 -note C5 -velocity 127[rb][rb]

lappend t2el [lb]list 0                [lb]midi::event note_on  -channel 0 -note C4 -velocity 127[rb][rb]
lappend t2el [lb]list 0                [lb]midi::event note_on  -channel 0 -note E4 -velocity 127[rb][rb]
lappend t2el [lb]list 0                [lb]midi::event note_on  -channel 0 -note G4 -velocity 127[rb][rb]
lappend t2el [lb]list 0                [lb]midi::event note_on  -channel 0 -note C5 -velocity 127[rb][rb]
lappend t2el [lb]list [lb]$mf clicks 1/1[rb] [lb]midi::event note_off -channel 0 -note C4 -velocity 127[rb][rb]
lappend t2el [lb]list 0                [lb]midi::event note_off -channel 0 -note E4 -velocity 127[rb][rb]
lappend t2el [lb]list 0                [lb]midi::event note_off -channel 0 -note G4 -velocity 127[rb][rb]
lappend t2el [lb]list 0                [lb]midi::event note_off -channel 0 -note C5 -velocity 127[rb][rb]

lappend t2el [lb]list 0                [lb]midi::event end_of_track[rb][rb]
set t2 [lb]midi::track -events $t2el[rb]

# Bass track
set t3el {}
lappend t3el [lb]list 0 [lb]midi::event text -value "Bass track"[rb][rb]
lappend t3el [lb]list 0 [lb]midi::event program_change -channel 1 -program "Electric Bass(pick)"[rb][rb]

lappend t3el [lb]list 0                [lb]midi::event note_on  -channel 1 -note C2 -velocity 127[rb][rb]
lappend t3el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 1 -note C2 -velocity 127[rb][rb]
lappend t3el [lb]list 0                [lb]midi::event note_on  -channel 1 -note D2 -velocity 127[rb][rb]
lappend t3el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 1 -note D2 -velocity 127[rb][rb]
lappend t3el [lb]list 0                [lb]midi::event note_on  -channel 1 -note E2 -velocity 127[rb][rb]
lappend t3el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 1 -note E2 -velocity 127[rb][rb]
lappend t3el [lb]list 0                [lb]midi::event note_on  -channel 1 -note F2 -velocity 127[rb][rb]
lappend t3el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 1 -note F2 -velocity 127[rb][rb]

lappend t3el [lb]list 0                [lb]midi::event note_on  -channel 1 -note E2 -velocity 127[rb][rb]
lappend t3el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 1 -note E2 -velocity 127[rb][rb]
lappend t3el [lb]list 0                [lb]midi::event note_on  -channel 1 -note F2 -velocity 127[rb][rb]
lappend t3el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 1 -note F2 -velocity 127[rb][rb]
lappend t3el [lb]list 0                [lb]midi::event note_on  -channel 1 -note G2 -velocity 127[rb][rb]
lappend t3el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 1 -note G2 -velocity 127[rb][rb]
lappend t3el [lb]list 0                [lb]midi::event note_on  -channel 1 -note A2 -velocity 127[rb][rb]
lappend t3el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 1 -note A2 -velocity 127[rb][rb]

lappend t3el [lb]list 0                [lb]midi::event note_on  -channel 1 -note G2 -velocity 127[rb][rb]
lappend t3el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 1 -note G2 -velocity 127[rb][rb]
lappend t3el [lb]list 0                [lb]midi::event note_on  -channel 1 -note A2 -velocity 127[rb][rb]
lappend t3el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 1 -note A2 -velocity 127[rb][rb]
lappend t3el [lb]list 0                [lb]midi::event note_on  -channel 1 -note B2 -velocity 127[rb][rb]
lappend t3el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 1 -note B2 -velocity 127[rb][rb]
lappend t3el [lb]list 0                [lb]midi::event note_on  -channel 1 -note C3 -velocity 127[rb][rb]
lappend t3el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 1 -note C3 -velocity 127[rb][rb]

lappend t3el [lb]list 0                [lb]midi::event note_on  -channel 1 -note C3 -velocity 127[rb][rb]
lappend t3el [lb]list [lb]$mf clicks 1/2[rb] [lb]midi::event note_off -channel 1 -note C3 -velocity 127[rb][rb]
lappend t3el [lb]list 0                [lb]midi::event note_on  -channel 1 -note G2 -velocity 127[rb][rb]
lappend t3el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 1 -note G2 -velocity 127[rb][rb]
lappend t3el [lb]list 0                [lb]midi::event note_on  -channel 1 -note E2 -velocity 127[rb][rb]
lappend t3el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 1 -note E2 -velocity 127[rb][rb]

lappend t3el [lb]list 0        [lb]midi::event note_on  -channel 1 -note C2 -velocity 127[rb][rb]
lappend t3el [lb]list [lb]$mf clicks 1/1[rb]   [lb]midi::event note_off -channel 1 -note C2 -velocity 127[rb][rb]

lappend t3el [lb]list 0 [lb]midi::event end_of_track[rb][rb]
set t3 [lb]midi::track -events $t3el[rb]

# Drum track
set t4el {}
lappend t4el [lb]list 0 [lb]midi::event text -value "Drum track"[rb][rb]

lappend t4el [lb]list 0                [lb]midi::event note_on  -channel 9 -note "closed hi-hat"      -velocity 127[rb][rb]
lappend t4el [lb]list 0                [lb]midi::event note_on  -channel 9 -note "acoustic bass drum" -velocity 127[rb][rb]
lappend t4el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 9 -note "closed hi-hat"      -velocity 127[rb][rb]
lappend t4el [lb]list 0                [lb]midi::event note_on  -channel 9 -note "closed hi-hat"      -velocity 127[rb][rb]
lappend t4el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 9 -note "closed hi-hat"      -velocity 127[rb][rb]
lappend t4el [lb]list 0                [lb]midi::event note_on  -channel 9 -note "closed hi-hat"      -velocity 127[rb][rb]
lappend t4el [lb]list 0                [lb]midi::event note_on  -channel 9 -note "acoustic snare"     -velocity 127[rb][rb]
lappend t4el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 9 -note "closed hi-hat"      -velocity 127[rb][rb]
lappend t4el [lb]list 0                [lb]midi::event note_on  -channel 9 -note "closed hi-hat"      -velocity 127[rb][rb]

for { set i 0 } { $i < 4 } { incr i } {
    lappend t4el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 9 -note "closed hi-hat"      -velocity 127[rb][rb]
    lappend t4el [lb]list 0                [lb]midi::event note_on  -channel 9 -note "closed hi-hat"      -velocity 127[rb][rb]
    lappend t4el [lb]list 0                [lb]midi::event note_off -channel 9 -note "acoustic bass drum" -velocity 127[rb][rb]
    lappend t4el [lb]list 0                [lb]midi::event note_on  -channel 9 -note "acoustic bass drum" -velocity 127[rb][rb]
    lappend t4el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 9 -note "closed hi-hat"      -velocity 127[rb][rb]
    lappend t4el [lb]list 0                [lb]midi::event note_on  -channel 9 -note "closed hi-hat"      -velocity 127[rb][rb]
    lappend t4el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 9 -note "closed hi-hat"      -velocity 127[rb][rb]
    lappend t4el [lb]list 0                [lb]midi::event note_on  -channel 9 -note "closed hi-hat"      -velocity 127[rb][rb]
    lappend t4el [lb]list 0                [lb]midi::event note_off -channel 9 -note "acoustic snare"     -velocity 127[rb][rb]
    lappend t4el [lb]list 0                [lb]midi::event note_on  -channel 9 -note "acoustic snare"     -velocity 127[rb][rb]
    lappend t4el [lb]list [lb]$mf clicks 1/4[rb] [lb]midi::event note_off -channel 9 -note "closed hi-hat"      -velocity 127[rb][rb]
    lappend t4el [lb]list 0                [lb]midi::event note_on  -channel 9 -note "closed hi-hat"      -velocity 127[rb][rb]
}

lappend t4el [lb]list 0 [lb]midi::event end_of_track[rb][rb]
set t4 [lb]midi::track -events $t4el[rb]

# Add tracks and write file
$mf configure -tracks [lb]list $t1 $t2 $t3 $t4[rb]
$mf write test.mid
$mf destroy

exit
[example_end]

The following examples uses the [cmd midi::file::measure] method to generate the
same note-on and note-off events as in the example above. This example requires
Tcl 8.5 because it uses the {*} operator.

[example_begin]
lappend auto_path ..
package require Tcl 8.5
package require midi

# Create midi file and initialise time division info
set mf [lb]midi::file -type 1 -time_division_type ticks_per_beat -ticks_per_beat 480[rb]

# Control track
set t1el {}
lappend t1el [lb]list 0 [lb]midi::event text -value "control track"[rb][rb]
lappend t1el [lb]list 0 [lb]midi::event tempo -tempo 0X7A120[rb][rb] ;# 120 Beats per minute
lappend t1el [lb]list 0 [lb]midi::event end_of_track[rb][rb]

set t1 [lb]midi::track -events $t1el[rb]

# Piano track
set at2el {}
lappend at2el [lb]list 0 [lb]midi::event text -value "Piano track"[rb][rb]
lappend at2el [lb]list 0 [lb]midi::event program_change -channel 0 -program "Electric Piano 2"[rb][rb]
lappend at2el {*}[lb]$mf measure -channel 0 -events {{1/1 C4} {1/1 E4} {1/1 G4} {1/1 C5} {1/1 {C4 E4 G4 C5}}}[rb]
lappend at2el [lb]list 0 [lb]midi::event end_of_track[rb][rb]

set t2 [lb]midi::track -events $at2el[rb]

# Bass track
set at3el {}
lappend at3el [lb]list 0 [lb]midi::event text -value "Bass track"[rb][rb]
lappend at3el [lb]list 0 [lb]midi::event program_change -channel 1 -program "Electric Bass(pick)"[rb][rb]
lappend at3el {*}[lb]$mf measure -channel 1 -events {{1/4 C2} {1/4 D2} {1/4 E2} {1/4 F2}}[rb]
lappend at3el {*}[lb]$mf measure -channel 1 -events {{1/4 E2 60} {1/4 F2} {1/4 G2} {1/4 A2}}[rb]
lappend at3el {*}[lb]$mf measure -channel 1 -events {{1/4 G2} {1/4 A2} {1/4 B2} {1/4  C3}}[rb]
lappend at3el {*}[lb]$mf measure -channel 1 -events {{1/2 C3} {1/4 G2} {1/4 E2}}[rb]
lappend at3el {*}[lb]$mf measure -channel 1 -events {{1/1 C2}}[rb]
lappend at3el [lb]list 0 [lb]midi::event end_of_track[rb][rb]

set t3 [lb]midi::track -events $at3el[rb]

# Drum track
set at4el {}
lappend at4el [lb]list 0 [lb]midi::event text -value "Drum track"[rb][rb]
for { set i 0 } { $i < 5 } { incr i } {
    lappend at4el {*}[lb]$mf measure -channel 9 -events {
        {1/4 {"closed hi-hat" "acoustic bass drum"}} \
	{1/4 {"closed hi-hat"}} \
        {1/4 {"closed hi-hat" "acoustic snare"}} \
        {1/4 {"closed hi-hat"}} \
	}[rb]
}
lappend at4el [lb]list 0 [lb]midi::event end_of_track[rb][rb]

set t4 [lb]midi::track -events $at4el[rb]

# Add tracks and write file
$mf configure -tracks [lb]list $t1 $t2 $t3 $t4[rb]
$mf write test2.mid
$mf destroy

exit
[example_end]

This example shows how the rests and the [cmd midi::merge] command can be used
to generate an event-list for the first track of the example above:

[example_begin]
set t1 [lb]midi::track -events $t1el[rb]

# Piano track
set at2el {}
lappend at2el [lb]list 0 [lb]midi::event text -value "Piano track"[rb][rb]
lappend at2el [lb]list 0 [lb]midi::event program_change -channel 0 -program "Electric Piano 2"[rb][rb]


set te1 [lb]$mf measure -channel 0 -events {{1/1 C4} {1/1 r}  {1/1 G4} {1/1 R}  {1/1 {r  E4 r  C5}}}[rb]
set te2 [lb]$mf measure -channel 0 -events {{1/1 R}  {1/1 E4} {1/1 r}  {1/1 C5} {1/1 {C4 r  G4 r }}}[rb]
lappend at2el {*}[lb]midi::merge $te1 $te2[rb]

lappend at2el [lb]list 0 [lb]midi::event end_of_track[rb][rb]

set t2 [lb]midi::track -events $at2el[rb]
[example_end]

This example reads the midi file specified on the command line and dumps the
contents to standard output:

[example_begin]
package require midi

set mf [lb]midi::file[rb]
$mf read [lb]lindex $argv 0[rb]
puts [lb]$mf dump[rb]
$mf destroy

exit
[example_end]

The result of the dump command looks like this:

[example_begin]
MThd
  header size: 6
  format type: 1
  number of tracks: 4
  time division: 480 ticks per beat

MTrk

  Delta time    Absolute time Event
  ------------- ------------- ----------------------------------------
              0             0 text control track
              0             0 tempo 500000
              0             0 end_of_track

MTrk

  Delta time    Absolute time Event
  ------------- ------------- ----------------------------------------
              0             0 text Piano track
              0             0 program_change channel 0x00, program 0x04
              0             0 note_on channel 0x00, note 0x3C, velocity 0x7F
           1920          1920 note_off channel 0x00, note 0x3C, velocity 0x7F
              0          1920 note_on channel 0x00, note 0x40, velocity 0x7F
           1920          3840 note_off channel 0x00, note 0x40, velocity 0x7F
              0          3840 note_on channel 0x00, note 0x43, velocity 0x7F
           1920          5760 note_off channel 0x00, note 0x43, velocity 0x7F
              0          5760 note_on channel 0x00, note 0x48, velocity 0x7F
           1920          7680 note_off channel 0x00, note 0x48, velocity 0x7F
              0          7680 note_on channel 0x00, note 0x3C, velocity 0x7F
              0          7680 note_on channel 0x00, note 0x40, velocity 0x7F
              0          7680 note_on channel 0x00, note 0x43, velocity 0x7F
              0          7680 note_on channel 0x00, note 0x48, velocity 0x7F
           1920          9600 note_off channel 0x00, note 0x3C, velocity 0x7F
              0          9600 note_off channel 0x00, note 0x40, velocity 0x7F
              0          9600 note_off channel 0x00, note 0x43, velocity 0x7F
              0          9600 note_off channel 0x00, note 0x48, velocity 0x7F
              0          9600 end_of_track

MTrk

  Delta time    Absolute time Event
  ------------- ------------- ----------------------------------------
              0             0 text Bass track
              0             0 program_change channel 0x01, program 0x22
              0             0 note_on channel 0x01, note 0x24, velocity 0x7F
            480           480 note_off channel 0x01, note 0x24, velocity 0x7F
              0           480 note_on channel 0x01, note 0x26, velocity 0x7F
            480           960 note_off channel 0x01, note 0x26, velocity 0x7F
              0           960 note_on channel 0x01, note 0x28, velocity 0x7F
            480          1440 note_off channel 0x01, note 0x28, velocity 0x7F
              0          1440 note_on channel 0x01, note 0x29, velocity 0x7F
            480          1920 note_off channel 0x01, note 0x29, velocity 0x7F
              0          1920 note_on channel 0x01, note 0x28, velocity 0x7F
            480          2400 note_off channel 0x01, note 0x28, velocity 0x7F
              0          2400 note_on channel 0x01, note 0x29, velocity 0x7F
            480          2880 note_off channel 0x01, note 0x29, velocity 0x7F
              0          2880 note_on channel 0x01, note 0x2B, velocity 0x7F
            480          3360 note_off channel 0x01, note 0x2B, velocity 0x7F
              0          3360 note_on channel 0x01, note 0x2D, velocity 0x7F
            480          3840 note_off channel 0x01, note 0x2D, velocity 0x7F
              0          3840 note_on channel 0x01, note 0x2B, velocity 0x7F
            480          4320 note_off channel 0x01, note 0x2B, velocity 0x7F
              0          4320 note_on channel 0x01, note 0x2D, velocity 0x7F
            480          4800 note_off channel 0x01, note 0x2D, velocity 0x7F
              0          4800 note_on channel 0x01, note 0x2F, velocity 0x7F
            480          5280 note_off channel 0x01, note 0x2F, velocity 0x7F
              0          5280 note_on channel 0x01, note 0x30, velocity 0x7F
            480          5760 note_off channel 0x01, note 0x30, velocity 0x7F
              0          5760 note_on channel 0x01, note 0x30, velocity 0x7F
            960          6720 note_off channel 0x01, note 0x30, velocity 0x7F
              0          6720 note_on channel 0x01, note 0x2B, velocity 0x7F
            480          7200 note_off channel 0x01, note 0x2B, velocity 0x7F
              0          7200 note_on channel 0x01, note 0x28, velocity 0x7F
            480          7680 note_off channel 0x01, note 0x28, velocity 0x7F
              0          7680 note_on channel 0x01, note 0x24, velocity 0x7F
           1920          9600 note_off channel 0x01, note 0x24, velocity 0x7F
              0          9600 end_of_track

MTrk

  Delta time    Absolute time Event
  ------------- ------------- ----------------------------------------
              0             0 text Drum track
              0             0 note_on channel 0x09, note 0x2A, velocity 0x7F
              0             0 note_on channel 0x09, note 0x24, velocity 0x7F
            480           480 note_on channel 0x09, note 0x2A, velocity 0x7F
            480           960 note_on channel 0x09, note 0x2A, velocity 0x7F
              0           960 note_on channel 0x09, note 0x26, velocity 0x7F
            480          1440 note_on channel 0x09, note 0x2A, velocity 0x7F
            480          1920 note_on channel 0x09, note 0x2A, velocity 0x7F
              0          1920 note_on channel 0x09, note 0x24, velocity 0x7F
            480          2400 note_on channel 0x09, note 0x2A, velocity 0x7F
            480          2880 note_on channel 0x09, note 0x2A, velocity 0x7F
              0          2880 note_on channel 0x09, note 0x26, velocity 0x7F
            480          3360 note_on channel 0x09, note 0x2A, velocity 0x7F
            480          3840 note_on channel 0x09, note 0x2A, velocity 0x7F
              0          3840 note_on channel 0x09, note 0x24, velocity 0x7F
            480          4320 note_on channel 0x09, note 0x2A, velocity 0x7F
            480          4800 note_on channel 0x09, note 0x2A, velocity 0x7F
              0          4800 note_on channel 0x09, note 0x26, velocity 0x7F
            480          5280 note_on channel 0x09, note 0x2A, velocity 0x7F
            480          5760 note_on channel 0x09, note 0x2A, velocity 0x7F
              0          5760 note_on channel 0x09, note 0x24, velocity 0x7F
            480          6240 note_on channel 0x09, note 0x2A, velocity 0x7F
            480          6720 note_on channel 0x09, note 0x2A, velocity 0x7F
              0          6720 note_on channel 0x09, note 0x26, velocity 0x7F
            480          7200 note_on channel 0x09, note 0x2A, velocity 0x7F
            480          7680 note_on channel 0x09, note 0x2A, velocity 0x7F
              0          7680 note_on channel 0x09, note 0x24, velocity 0x7F
            480          8160 note_on channel 0x09, note 0x2A, velocity 0x7F
            480          8640 note_on channel 0x09, note 0x2A, velocity 0x7F
              0          8640 note_on channel 0x09, note 0x26, velocity 0x7F
            480          9120 note_on channel 0x09, note 0x2A, velocity 0x7F
              0          9120 end_of_track
[example_end]

[section Events]

[list_begin definitions]

[lst_item sequence_number] Event containing the sequence number of the track in
 which this event is placed.

[list_begin opt]
[opt_def -value integer] The sequence number of the track. The default value
is [const 0]. 
[opt_def "" ""]
[list_end]

[lst_item text] Text describing the track in which this event is placed.

[list_begin opt]
[opt_def -value string] File or track description. The default value is an 
empty string.
[opt_def "" ""]
[list_end]

[lst_item copyright] Midi file copyright notice.

[list_begin opt]
[opt_def -value string] Copyright text. The default value is an empty 
string.
[opt_def "" ""]
[list_end]

[lst_item track_name] Name of track.

[list_begin opt]
[opt_def -value string] Track name. The default value is an empty string.
[opt_def "" ""]
[list_end]

[lst_item instrument_name] Name of instrument used in track.

[list_begin opt]
[opt_def -value string] Instrument name. The default value is an empty string.
[opt_def "" ""]
[list_end]

[lst_item lyric] Lyric to be sung at the point this event is placed. This can 
be a word or syllable.

[list_begin opt]
[opt_def -value string] Lyric. The default value is an empty string.
[opt_def "" ""]
[list_end]

[lst_item marker] Marker for specific point in track like rehearsal letter, 
section name, loop start or loop end.

[list_begin opt]
[opt_def -value string] Marker text. The default value is an empty string.
[opt_def "" ""]
[list_end]

[lst_item cue_point] Description of something which happens at the point this 
event is placed.

[list_begin opt]
[opt_def -value string] Descriptive text. The default value is an empty string.
[opt_def "" ""]
[list_end]

[lst_item program_name] Name of the program used in the events following.

[list_begin opt]
[opt_def -value string] Program name. The default value is an empty string.
[opt_def "" ""]
[list_end]

[lst_item device_name] Name of the midi device (port) where the track is 
routed.

[list_begin opt]
[opt_def -value string] Device name. The default value is an empty string.
[opt_def "" ""]
[list_end]

[lst_item channel] Specifies the channel to which following meta and system 
exclusive must be sent. (DEPRECATED)

[list_begin opt]
[opt_def -channel integer] Channel number. The default value is 0. Check the 
[sectref Channels] section for valid channel numbers.
[opt_def "" ""]
[list_end]

[lst_item port] Midi port to which following midi events must be sent. 
(DEPRECATED)

[list_begin opt]
[opt_def -port] Port number. The default value is 0.
[opt_def "" ""]
[list_end]

[lst_item end_of_track] Marks the end of a track. Must be placed at the end of 
every track. 

[lst_item tempo] Used to indicate tempo changes. 

[list_begin opt]
[opt_def -tempo integer] Tempo expressed in micro seconds per quarter note. The
default value is 0x07A120 which corresponds to 120 BPM.
[opt_def "" ""]
[list_end]

[lst_item smpte_offset] Specifies the start time of the track. 

[list_begin opt]
[opt_def -hours integer] Hours part of start time. Default value is 0.
[opt_def -minutes integer] Minutes part of start time. Default value is 0.
[opt_def -seconds integer] Seconds part of start time. Default value is 0.
[opt_def -frames integer] Frame count part of start time. Default value is 0.
[opt_def -framefractions integer] Frame fraction part of start time. Default 
value is 0.
[opt_def "" ""]
[list_end]

[lst_item time_signature] Used to specify the time signature.

[list_begin opt]
[opt_def -numerator integer] Numerator part of time signature. Default value is
0.
[opt_def -denominator integer] Denominator part of the time signature. This 
values must be an integer power of 2 (2, 4, 8). Default value is 1.
[opt_def -clocks_ticks_between_metronome_clicks integer] The number of midi 
clock cliks in one metronome click. Default value is 0. 
[opt_def -notated_32nd_notes_in_quarter_note integer] The number of notated 
32nd notes in a midi quarter note. Default value is 0.
[opt_def "" ""]
[list_end]

[lst_item key_signature] Sets the key signature.

[list_begin opt]
[opt_def -number_of_modifications integer] The number of modifications. 
Positive  numbers (1..7) for sharps, negative numbers (-1..-7) for flats. 
Default value is 0.
[opt_def -scale integer] Set to 0 for major scale or to 1 for minor scale. 
Default values is 0.
[opt_def "" ""]
[list_end]

[lst_item sequencer_specific] Used to send data to a sequencer. These events 
are not interpreted by this packages. 

[list_begin opt]
[opt_def -data listOfIntegers] The data to be sent as a list of integers 
without the size of the data. Default value is an empty list. 
[opt_def "" ""]
[list_end]

[lst_item meta_unknown] Meta event. These events are not interpreted by this 
packages. 

[list_begin opt]
[opt_def -meta_unknown_event_type integer] Meta event type. Default values is 
0.
[opt_def -data listOfIntegers] Data associated with the meta event specified as
a list of integers without the size of the data. Default value is an empty 
list.
[opt_def "" ""]
[list_end]

[lst_item SysEx] System exclusive event. These events are not interpreted by 
this packages. 

[list_begin opt]
[opt_def -sysex_event_type] System exclusive event type. Default values is 0.
[opt_def -data] Data associated with the system exclusive event specified as
a list of integers without the size of the data. Default value is an empty 
list.
[opt_def "" ""]
[list_end]

[lst_item note_on] Play a note.

[list_begin opt]
[opt_def -channel integer] Channel on which to play the note. Check the 
[sectref Channels] section for valid channel numbers. Default value is 0.
[opt_def -note note] Note to play. Check the [sectref Notes] section for 
valid note numbers and valid note names. Default value is 0. 
[opt_def -velocity integer] Velocity (volume) with which to hit the note. Must 
be an integer in the range 0..127. Default value is 0.
[opt_def "" ""]
[list_end]

[lst_item note_off] Stop a note.

[list_begin opt]
[opt_def -channel integer] Channel on which to stop the note. Check the 
[sectref Channels] section for valid channel numbers. Default value is 0.
[opt_def -note note] Note to stop. Check the [sectref Notes] section for 
valid note numbers and valid note names. Default value is 0. 
[opt_def -velocity integer] Velocity (volume) with which to stop the note. Must
be an integer in the range 0..127. Default value is 0.
[opt_def "" ""]
[list_end]

[lst_item note_aftertouch] Change the pressure with which the note is held 
down. This can be used to control effects (e.g. a vibrato).

[list_begin opt]
[opt_def -channel integer] Channel on which to apply the aftertouch. Check the 
[sectref Channels] section for valid channel numbers. Default value is 0.
[opt_def -note note] Note to apply aftertouch to. Check the [sectref Notes] 
section for  valid note numbers and valid note names. Default value is 0. 
[opt_def -amount integer] Amount of aftertouch to apply to the note. Must
be an integer in the range 0..127. Default value is 0.
[opt_def "" ""]
[list_end]

[lst_item controller] Used to set the value of a controller (e.g. modulation 
wheel).

[list_begin opt]
[opt_def -channel integer] Channel on which controller will have effect. Check 
the [sectref Channels] section for valid channel numbers. Default value is 0. 
[opt_def -controller controller] Controller name or number. Check the 
[sectref Controllers] section for valid controller names and numbers. Default 
value is 0.
[opt_def -value integer] Value to be set for the specified controller. Must
be an integer in the range 0..127. Default value is 0.
[opt_def "" ""]
[list_end]

[lst_item program_change] change the program (patch, instrument) for a channel.

[list_begin opt]
[opt_def -channel integer] Channel on which program change will have effect. 
Check  the [sectref Channels] section for valid channel numbers. Default value 
is 0. 
[opt_def -program program] Program name or number. Check the 
[sectref Programs] section for valid program names and numbers. Default value 
is 0.
[opt_def "" ""]
[list_end]

[lst_item channel_aftertouch] Change the pressure with which all notes in the 
specified channel are held down. This can be used to control effects (e.g. a 
vibrato).

[list_begin opt]
[opt_def -channel integer] Channel on which to apply the aftertouch. Check the 
[sectref Channels] section for valid channel numbers. Default value is 0.
[opt_def -amount integer] Amount of aftertouch to apply to the channel. Must
be an integer in the range 0..127. Default value is 0.
[opt_def "" ""]
[list_end]


[lst_item pitch_bend] Used to change the pitch of all notes in a channel.

[list_begin opt]
[opt_def -channel integer] Channel on which to apply the aftertouch. Check the 
[sectref Channels] section for valid channel numbers. Default value is 0.
[opt_def -amount integer] Amount of bend. Must be an integer in the range 
-8192..8191. Values less than zero lower the pitch, values larger than zero 
increase the pitch. 
[opt_def "" ""]
[list_end]
 
[list_end]

[section Channels]

A midi file can store data for 16 channels. Valid channel numbers are in the 
range 0..15. Real channel numbers must be specified. Often midi channels are 
numbered starting from 1. When using this package, the first channel is channel
zero. 

[section Notes]

A midi file knows 128 notes. They are represented by an integer in the range 
0..127. The note with number 69 is an A with pitch of 440Hz. 

Notes can be specified using their number or using an alphanumeric notation. 
This notation has the following structure:

[example_begin]
<note><modifiers><octave>
[example_end]

[list_begin bullet]

[bullet]Valid notes are [const A], [const B], [const C], [const D], [const E],
[const F] and [const G]. The notes can be specified in upper or lower case. 

[bullet]Valid modifiers are [const #] and [const b]. The modifiers can be
specified in upper or lower case.

[bullet]Valid octaves are [const -1] to 9.

[list_end]

Some examples:

[example_begin]
A4
Bb7
F#3
C##4
abb3
e#b#b#b6
[example_end]

When representing notes with their numbers, valid notes are:

[example_begin]
Number Note  Octave
------ ----- ------
     0     C     -1
     1 C#/Db     -1
     2     D     -1
     3 D#/Eb     -1
     4     E     -1
     5     F     -1
     6 F#/Gb     -1
     7     G     -1
     8  G#Ab     -1
     9     A     -1
    10 A#/Bb     -1
    11     B     -1
    12     C      0
    13 C#/Db      0
    14     D      0
    15 D#/Eb      0
    16     E      0
    17     F      0
    18 F#/Gb      0
    19     G      0
    20  G#Ab      0
    21     A      0
    22 A#/Bb      0
    23     B      0
    24     C      1
    25 C#/Db      1
    26     D      1
    27 D#/Eb      1
    28     E      1
    29     F      1
    30 F#/Gb      1
    31     G      1
    32  G#Ab      1
    33     A      1
    34 A#/Bb      1
    35     B      1
    36     C      2
    37 C#/Db      2
    38     D      2
    39 D#/Eb      2
    40     E      2
    41     F      2
    42 F#/Gb      2
    43     G      2
    44  G#Ab      2
    45     A      2
    46 A#/Bb      2
    47     B      2
    48     C      3
    49 C#/Db      3
    50     D      3
    51 D#/Eb      3
    52     E      3
    53     F      3
    54 F#/Gb      3
    55     G      3
    56  G#Ab      3
    57     A      3
    58 A#/Bb      3
    59     B      3
    60     C      4
    61 C#/Db      4
    62     D      4
    63 D#/Eb      4
    64     E      4
    65     F      4
    66 F#/Gb      4
    67     G      4
    68  G#Ab      4
    69     A      4
    70 A#/Bb      4
    71     B      4
    72     C      5
    73 C#/Db      5
    74     D      5
    75 D#/Eb      5
    76     E      5
    77     F      5
    78 F#/Gb      5
    79     G      5
    80  G#Ab      5
    81     A      5
    82 A#/Bb      5
    83     B      5
    84     C      6
    85 C#/Db      6
    86     D      6
    87 D#/Eb      6
    88     E      6
    89     F      6
    90 F#/Gb      6
    91     G      6
    92  G#Ab      6
    93     A      6
    94 A#/Bb      6
    95     B      6
    96     C      7
    97 C#/Db      7
    98     D      7
    99 D#/Eb      7
   100     E      7
   101     F      7
   102 F#/Gb      7
   103     G      7
   104  G#Ab      7
   105     A      7
   106 A#/Bb      7
   107     B      7
   108     C      8
   109 C#/Db      8
   110     D      8
   111 D#/Eb      8
   112     E      8
   113     F      8
   114 F#/Gb      8
   115     G      8
   116  G#Ab      8
   117     A      8
   118 A#/Bb      8
   119     B      8
   120     C      9
   121 C#/Db      9
   122     D      9
   123 D#/Eb      9
   124     E      9
   125     F      9
   126 F#/Gb      9
   127     G      9
[example_end]

When playing a note on channel 9, one of the following percussion sound names 
can be used to specify the note:

[example_begin]
Number Sound
------ ------------------
    35 Acoustic Bass Drum     
    36 Bass Drum 1            
    37 Side Stick             
    38 Acoustic Snare         
    39 Hand Clap              
    40 Electric Snare         
    41 Low Floor Tom          
    42 Closed Hi-Hat          
    43 High Floor Tom         
    44 Pedal Hi-Hat           
    45 Low Tom                
    46 Open Hi-Hat            
    47 Low-Mid Tom            
    48 Hi-Mid Tom             
    49 Crash Cymbal 1         
    50 High Tom               
    51 Ride Cymbal 1          
    52 Chinese Cymbal         
    53 Ride Bell              
    54 Tambourine             
    55 Splash Cymbal          
    56 Cowbell                
    57 Crash Cymbal 2         
    58 Vibraslap
    59 Ride Cymbal 2      
    60 Hi Bongo           
    61 Low Bongo          
    62 Mute Hi Conga      
    63 Open Hi Conga      
    64 Low Conga          
    65 High Timbale       
    66 Low Timbale        
    67 High Agogo         
    68 Low Agogo          
    69 Cabasa             
    70 Maracas            
    71 Short Whistle      
    72 Long Whistle       
    73 Short Guiro        
    74 Long Guiro         
    75 Claves             
    76 Hi Wood Block      
    77 Low Wood Block     
    78 Mute Cuica         
    79 Open Cuica         
    80 Mute Triangle      
    81 Open Triangle      
[example_end]

These precussion sound names can be specified case insensitive.

[section Controllers]

Controllers can be specified with their name or number. Controller names are 
case insensitive. The defined controllers are:

[example_begin]
Ctrl Description
---- ---------------------------------------------
   0 Bank Select (coarse)                               
   1 Modulation Wheel (coarse)                          
   2 Breath controller (coarse)                         
   4 Foot Pedal (coarse)                                
   5 Portamento Time (coarse)                           
   6 Data Entry (coarse)                                
   7 Volume (coarse)                                    
   8 Balance (coarse)                                   
  10 Pan position (coarse)                              
  11 Expression (coarse)                                
  12 Effect Control 1 (coarse)                          
  13 Effect Control 2 (coarse)                          
  16 General Purpose Slider 1                           
  17 General Purpose Slider 2                           
  18 General Purpose Slider 3                           
  19 General Purpose Slider 4                           
  32 Bank Select (fine)                                 
  33 Modulation Wheel (fine)                            
  34 Breath controller (fine)                           
  36 Foot Pedal (fine)                                  
  37 Portamento Time (fine)                             
  38 Data Entry (fine)                                  
  39 Volume (fine)                                      
  40 Balance (fine)                                     
  42 Pan position (fine)                                
  43 Expression (fine)                                  
  44 Effect Control 1 (fine)                            
  45 Effect Control 2 (fine)                            
  64 Hold Pedal (on/off)                                
  65 Portamento (on/off)                                
  66 Sustenuto Pedal (on/off)                           
  67 Soft Pedal (on/off)                                
  68 Legato Pedal (on/off)                              
  69 Hold 2 Pedal (on/off)                              
  70 Sound Variation                                    
  71 Sound Timbre                                       
  72 Sound Release Time                                 
  73 Sound Attack Time                                  
  74 Sound Brightness                                   
  75 Sound Control 6                                    
  76 Sound Control 7                                    
  77 Sound Control 8                                    
  78 Sound Control 9                                    
  79 Sound Control 10                                   
  80 General Purpose Button 1 (on/off)                  
  81 General Purpose Button 2 (on/off)                  
  82 General Purpose Button 3 (on/off)                  
  83 General Purpose Button 4 (on/off)                  
  91 Effects Level                                      
  92 Tremulo Level                                      
  93 Chorus Level                                       
  94 Celeste Level                                      
  95 Phaser Level                                       
  96 ata Button increment                               
  97 Data Button decrement                              
  98 Non-registered Parameter (fine)                    
  99 Non-registered Parameter (coarse)                  
 100 Registered Parameter (fine)                        
 101 Registered Parameter (coarse)                      
 120 All Sound Off                                      
 121 All Controllers Off                                
 122 Local Keyboard (on/off)                            
 123 All Notes Off                                      
 124 Omni Mode Off                                      
 125 Omni Mode On                                       
 126 Mono Operation                                     
 127 Poly Operation                                     
[example_end]

[section Programs]

Program names (also known as patches or instruments) can be specified with
their name or number. Names are case insensitive. Programs known in the General
Midi standard are:

[example_begin]
Program Family               Description
------- -------------------- -----------
      0 Piano                Acoustic Grand        
      1 Piano                Bright Acoustic       
      2 Piano                Electric Grand        
      3 Piano                Honky-Tonk            
      4 Piano                Electric Piano 1      
      5 Piano                Electric Piano 2      
      6 Piano                Harpsichord           
      7 Piano                Clavinet              
      8 Chromatic percussion Celesta      
      9 Chromatic percussion Glockenspiel 
     10 Chromatic percussion Music Box    
     11 Chromatic percussion Vibraphone   
     12 Chromatic percussion Marimba      
     13 Chromatic percussion Xylophone    
     14 Chromatic percussion Tubular Bells
     15 Chromatic percussion Dulcimer     
     16 Organ                Drawbar Organ         
     17 Organ                Percussive Organ      
     18 Organ                Rock Organ            
     19 Organ                Church Organ          
     20 Organ                Reed Organ            
     21 Organ                Accoridan             
     22 Organ                Harmonica             
     23 Organ                Tango Accordian       
     24 Guitar               Nylon String Guitar   
     25 Guitar               Steel String Guitar   
     26 Guitar               Electric Jazz Guitar  
     27 Guitar               Electric Clean Guitar 
     28 Guitar               Electric Muted Guitar 
     29 Guitar               Overdriven Guitar     
     30 Guitar               Distortion Guitar     
     31 Guitar               Guitar Harmonics      
     32 Bass                 Acoustic Bass             
     33 Bass                 Electric Bass(finger)     
     34 Bass                 Electric Bass(pick)       
     35 Bass                 Fretless Bass             
     36 Bass                 Slap Bass 1               
     37 Bass                 Slap Bass 2               
     38 Bass                 Synth Bass 1              
     39 Bass                 Synth Bass 2              
     40 Solo strings         Violin             
     41 Solo strings         Viola              
     42 Solo strings         Cello              
     43 Solo strings         Contrabass         
     44 Solo strings         Tremolo Strings    
     45 Solo strings         Pizzicato Strings  
     46 Solo strings         Orchestral Strings 
     47 Solo strings         Timpani            
     48 Ensemble             String Ensemble 1         
     49 Ensemble             String Ensemble 2         
     50 Ensemble             SynthStrings 1            
     51 Ensemble             SynthStrings 2            
     52 Ensemble             Choir Aahs                
     53 Ensemble             Voice Oohs                
     54 Ensemble             Synth Voice               
     55 Ensemble             Orchestra Hit             
     56 Brass                Trumpet        
     57 Brass                Trombone       
     58 Brass                Tuba           
     59 Brass                Muted Trumpet  
     60 Brass                French Horn    
     61 Brass                Brass Section  
     62 Brass                SynthBrass 1   
     63 Brass                SynthBrass 2   
     64 Reed                 Soprano Sax               
     65 Reed                 Alto Sax                  
     66 Reed                 Tenor Sax                 
     67 Reed                 Baritone Sax              
     68 Reed                 Oboe                      
     69 Reed                 English Horn              
     70 Reed                 Bassoon                   
     71 Reed                 Clarinet                  
     72 Pipe                 Piccolo     
     73 Pipe                 Flute       
     74 Pipe                 Recorder    
     75 Pipe                 Pan Flute   
     76 Pipe                 Blown Bottle
     77 Pipe                 Skakuhachi  
     78 Pipe                 Whistle     
     79 Pipe                 Ocarina     
     80 Synth lead           Lead 1 (square)           
     81 Synth lead           Lead 2 (sawtooth)         
     82 Synth lead           Lead 3 (calliope)         
     83 Synth lead           Lead 4 (chiff)            
     84 Synth lead           Lead 5 (charang)          
     85 Synth lead           Lead 6 (voice)            
     86 Synth lead           Lead 7 (fifths)           
     87 Synth lead           Lead 8 (bass+lead)        
     88 Synth pad            Pad 1 (new age)    
     89 Synth pad            Pad 2 (warm)      
     90 Synth pad            Pad 3 (polysynth) 
     91 Synth pad            Pad 4 (choir)     
     92 Synth pad            Pad 5 (bowed)     
     93 Synth pad            Pad 6 (metallic)  
     94 Synth pad            Pad 7 (halo)      
     95 Synth pad            Pad 8 (sweep)     
     96 Synth effects        FX 1 (rain)               
     97 Synth effects        FX 2 (soundtrack)         
     98 Synth effects        FX 3 (crystal)            
     99 Synth effects        FX 4 (atmosphere)         
    100 Synth effects        FX 5 (brightness)         
    101 Synth effects        FX 6 (goblins)            
    102 Synth effects        FX 7 (echoes)             
    103 Synth effects        FX 8 (sci-fi)              
    104 Ethnic               Sitar   
    105 Ethnic               Banjo   
    106 Ethnic               Shamisen
    107 Ethnic               Koto    
    108 Ethnic               Kalimba 
    109 Ethnic               Bagpipe 
    110 Ethnic               Fiddle  
    111 Ethnic               Shanai  
    112 Percussive           Tinkle Bell               
    113 Percussive           Agogo                     
    114 Percussive           Steel Drums               
    115 Percussive           Woodblock                 
    116 Percussive           Taiko Drum                
    117 Percussive           Melodic Tom               
    118 Percussive           Synth Drum                
    119 Percussive           Reverse Cymbal            
    120 Sound effects        Guitar Fret Noise
    121 Sound effects        Breath Noise     
    122 Sound effects        Seashore         
    123 Sound effects        Bird Tweet       
    124 Sound effects        Telephone Ring   
    125 Sound effects        Helicopter       
    126 Sound effects        Applause         
    127 Sound effects        Gunshot          
[example_end]

Some midi devices may provide different drum kits for channel 9. General midi 
provides only one. 
  
[keywords midi]

[manpage_end]
